﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Stl.Controls
{
    /// <summary>
    /// une extension du composant ComboBoxEnh qui permette de gérer automatiquement la liste déroulante,
    /// il s’agit simplement d’ajouter à la liste les chaînes qui sont validées au niveau de ComboBoxEnh. 
    /// </summary>
    [ToolboxBitmap(typeof(ComboBoxIndex), "ComboBoxIndex.bmp")]
    public partial class ComboBoxIndex : ComboBoxEnh
    {
        //************************** Champs ******************************//

        /// <summary>
        /// Les quatres styles qui affectent les comportements du control
        /// </summary>
        [Flags]
        [TypeConverter(typeof(Psl.Converters.EnumFlagsConverter))]
        public enum ListStyles
        {
            None = 0x0,         // Aucune option armée
            AutoInsert = 0x1,   // Ajouter automatiquement les chaînes validées            
            AutoLimit = 0x2,    // Limiter le nombre d'entrées dans le cas d'une gestion en historique LRU
            All = 0x3,          // Toutes options armées
        }

        /// <summary>
        /// Valeur par défaut de la propriété ListLimit
        /// </summary>
        public const int DefaultLimit = 40;

        // variables private pour les propriétés
        private ListStyles listStyle = ListStyles.None;
        private int listLimit = 40; //DefaultLimit;

        
        // propriétés
        [DefaultValue(ListStyles.None)]
        public ListStyles ListStyle
        {
            get
            {
                return listStyle;
            }
            set
            {
                if (listStyle == value)
                    return;
                else
                    listStyle = value;                
                OnListStyleChanged(new EventArgs());
            }

        }

        /// <summary>
        /// 
        /// </summary>
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        [DefaultValue(false)]
        public bool AutoInsert
        {
            get
            {
                return (ListStyle & ListStyles.AutoInsert) != 0;
            }
            set
            {   
                ListStyle = value ? (ListStyle | ListStyles.AutoInsert) : (ListStyle & ~ListStyles.AutoInsert);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        [DefaultValue(false)]
        public bool AutoLimit
        {
            get
            {
                return (ListStyle & ListStyles.AutoLimit) != 0;
            }
            set
            {
                ListStyle = value ? (ListStyle | ListStyles.AutoLimit) : (ListStyle & ~ListStyles.AutoLimit);
            }
        }

        /// <summary>
        /// La taille maximume de la liste déroulant du control, effectif si la propriété AutoLimit est armée
        /// </summary>
        [DefaultValue(DefaultLimit)]
        public int ListLimit
        {
            get { return listLimit; }
            set { listLimit = value; }
        }

        // event handler
        public event EventHandler ListStyleChanged;

        //************************** Méthodes ******************************//
        
        // constructeur
        public ComboBoxIndex()
        {
            InitializeComponent();
        }

        // méthodes auxilliaires

        /// <summary>
        /// Ajouter une chaine de caractère dans la liste de combobox
        /// </summary>
        /// <param name="text">Texte à ajouter dans la liste</param>
        public void TextEnter( string text ) 
        {
            if (AutoInsert)
            {
                int pos = AddItem(text);
                if (DropDownStyle == ComboBoxStyle.DropDownList)
                    this.SelectedIndex = pos;
            }
        }

        /// <summary>
        /// Ajouter un item dans la liste
        /// </summary>
        /// <param name="text">text</param>
        /// <returns>Position de l'item inseré, ou de l'item trouvé.</returns>
        protected int AddItem(string text)
        {
            int pos = FindStringExact(text);
            if ( pos == -1)
            {                
                if (Sorted)
                    pos = Items.Add(text);
                else
                {
                    pos = 0;
                    Items.Insert(pos, text);
                    RemoveListBoxItems(ListLimit);
                }
            }
            return pos;
        }

        // supprime les items de listbox en trop
        // on garde nb items
        private void RemoveListBoxItems(int nb)
        {
            if (AutoLimit)
            {
                int count = Items.Count;
                while (count > nb && nb > 0)
                {
                    Items.RemoveAt(--count);
                }
            }
        }


        //************************** Evenements ******************************//

        protected void OnListStyleChanged(EventArgs e)
        {
            if(ListStyleChanged != null)
                ListStyleChanged(this, e);
        }

        protected override void OnTextValidated(EventArgs e)
        {
            base.OnTextValidated(e);
            if (AutoInsert)
                TextEnter(this.Text);
        }
    }
}
